/*
 *  (C) Copyright 2008 Insula T.I. Ltda.
 * 
 *  This file is part of Vulcano.
 *
 *  Vulcano is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Vulcano is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with Vulcano.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.openinsula.vulcano.orm.dao.hibernate;

import static org.junit.Assert.assertEquals;

import java.util.List;

import org.junit.Test;
import org.openinsula.vulcano.orm.dao.query.DaoQuery;
import org.openinsula.vulcano.orm.dao.query.ProjectionDaoQuery;
import org.openinsula.vulcano.orm.dao.query.SimpleDaoQuery;
import org.openinsula.vulcano.orm.dao.query.builder.DaoSelect;
import org.openinsula.vulcano.orm.dao.query.projection.MaxProjection;
import org.openinsula.vulcano.orm.dao.query.spec.AndSpec;
import org.openinsula.vulcano.orm.dao.query.spec.EqualsSpec;
import org.openinsula.vulcano.orm.entity.Person;
import org.openinsula.vulcano.orm.entity.Pet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;

@ContextConfiguration
public class HibernateDaoTestCase extends AbstractTransactionalJUnit4SpringContextTests {

	@Autowired
	private HibernateDao hibernateDao;

	@Test
	public void testPersist() {
		populateDatabase();

		assertEquals(1, countRowsInTable("Person"));
		assertEquals(2, countRowsInTable("Pet"));
	}

	@Test
	public void testRemove() {
		populateDatabase();

		DaoQuery<Pet> petDaoQuery = new SimpleDaoQuery<Pet>(Pet.class);

		List<Pet> result = hibernateDao.find(petDaoQuery);

		hibernateDao.remove(result.get(0), result.get(1));
		hibernateDao.flush();

		assertEquals(0, countRowsInTable("Pet"));
	}

	@Test
	public void testFind() {
		populateDatabase();

		DaoQuery<Person> personDaoQuery = new SimpleDaoQuery<Person>(Person.class, new AndSpec(new EqualsSpec("name",
				"Obi Wan"), new EqualsSpec("age", 25)));

		List<Person> result = hibernateDao.find(personDaoQuery);

		assertEquals(1, result.size());

		DaoQuery<Pet> petDaoQuery = new SimpleDaoQuery<Pet>(Pet.class, new EqualsSpec("person", result.get(0)));

		assertEquals(2, hibernateDao.find(petDaoQuery).size());

		DaoQuery<Integer> ageDaoQuery = new ProjectionDaoQuery<Integer>(Person.class, new MaxProjection("age"));

		assertEquals(25, hibernateDao.findUnique(ageDaoQuery).intValue());
	}

	@Test(expected = IllegalStateException.class)
	public void testFindUnique() {
		populateDatabase();

		DaoQuery<Pet> daoQuery = new SimpleDaoQuery<Pet>(Pet.class);

		hibernateDao.findUnique(daoQuery);
	}

	@Test
	public void testCountWithDaoSelect() {
		populateDatabase();

		assertEquals(2L, hibernateDao.findUnique(new DaoSelect<Long>().count().from(Pet.class).toQuery()).longValue());

		assertEquals(0L, hibernateDao.findUnique(
				new DaoSelect<Long>().count().from(Person.class).eq("name", "Yoda").toQuery()).longValue());
	}

	@Test
	public void testPropertiesWithDaoSelect() {
		populateDatabase();

		assertEquals("Obi Wan", hibernateDao.findUnique(new DaoSelect<String>().props("name").from(Person.class).eq(
				"age", 25).toQuery()));
	}

	private void populateDatabase() {
		Person person = new Person();
		person.setName("Obi Wan");
		person.setAge(25);
		person.setJedi(true);

		Pet dog = new Pet();
		dog.setName("Woofy");
		dog.setPerson(person);

		Pet cat = new Pet();
		cat.setPerson(person);
		cat.setName("Simm");

		hibernateDao.persist(person, dog, cat);
	}

}
